package core;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;


public class SendBroadcast {

    private static int SendPort = 4446;

    public static boolean findAllServers(List<Machine> serverNames)
    {
        serverNames.clear();
        ReceiveResponse recv = new  ReceiveResponse(serverNames);
        recv.start();

        DatagramSocket datagramSocket;
        try {
            datagramSocket = new DatagramSocket(SendPort);
            datagramSocket.setSoTimeout(1000);
        }
        catch (SocketException ex)
        {
            ex.printStackTrace();
            recv.stopThread();
            return false;
        }
        byte[] buf  = new byte[10];
        Enumeration<NetworkInterface> en;
        try {
            en = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException ex) {
            ex.printStackTrace();
            recv.stopThread();
            return false;
        }

        while (en.hasMoreElements()) {
            try {
                NetworkInterface ni = en.nextElement();
                if (ni.getHardwareAddress() != null) {
                    List<InterfaceAddress> list = ni.getInterfaceAddresses();
                    Iterator<InterfaceAddress> it = list.iterator();
                    while (it.hasNext()) {
                        InterfaceAddress ia = it.next();
                        InetAddress addr = ia.getBroadcast();
                        DatagramPacket packet;
                        packet = new DatagramPacket(buf, buf.length,
                                        addr, SendPort);
                        try {
                            datagramSocket.send(packet);
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }

                    }
                }
            } catch (SocketException ex) {
                ex.printStackTrace();
                recv.stopThread();
                return false;
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            recv.stopThread();
            return false;
        }
        datagramSocket.close();
        recv.stopThread();

        return true;
    }

    public static Machine findServer(String DestinationIP)
    {
        Machine server = null;
        List<Machine> serverNames = new ArrayList<Machine>();
        
        ReceiveResponse recv = new  ReceiveResponse(serverNames);
        recv.start();

        DatagramSocket datagramSocket;
        try {
            datagramSocket = new DatagramSocket(SendPort);
            datagramSocket.setSoTimeout(1000);
        }
        catch (SocketException ex)
        {
            ex.printStackTrace();
            recv.stopThread();
            return server;
        }
        byte[] buf  = new byte[10];
        InetAddress addr = null;
        try{
            addr = InetAddress.getByName(DestinationIP);
        }catch (UnknownHostException ex)
        {
            ex.printStackTrace();
            return server;
        }
        DatagramPacket packet;
        packet = new DatagramPacket(buf, buf.length, addr, SendPort);
        try {
            datagramSocket.send(packet);
        } catch (IOException ex) {
            ex.printStackTrace();
            return server;
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            recv.stopThread();
            return server;
        }
        datagramSocket.close();
        recv.stopThread();
        if (serverNames.size() > 0)
        {
            server = serverNames.get(0);
        }
        return server;
    }
    public static void main(String[] args) {
        List<Machine> list = new ArrayList<Machine>();
        findAllServers(list);

    }
}

class ReceiveResponse extends Thread
{
    private List<Machine> names;
    private static boolean isRunning = false;
    private static boolean isEnd = false;
    private static int ReceivePort = 4447;

    public ReceiveResponse(List<Machine> serverNames) {
        names = serverNames;
    }

    public void run() {
        isRunning = true;
        byte[] buf = new byte[256];
        DatagramPacket packet = null;
        DatagramSocket datagramSocket;
        try {
            datagramSocket = new DatagramSocket(ReceivePort);
            datagramSocket.setSoTimeout(1000);
        }
        catch (SocketException ex)
        {
            ex.printStackTrace();
            return;
        }

        while (isRunning) {
            try{
                packet = new DatagramPacket(buf, buf.length);
                datagramSocket.receive(packet);

            } catch (IOException ex) {
                ex.printStackTrace();
                continue;
            }
            InetAddress addr = packet.getAddress();
            System.out.println("Response from " + addr.getHostAddress());
            Machine curr = new Machine();
            curr.MachineName = new String(buf, 0, packet.getLength());
            curr.IP_String = addr.getHostAddress();
            names.add(curr);
        }
        datagramSocket.close();
        isEnd = true;
    }

    public void stopThread()
    {
        isRunning = false;
        while (!isEnd)
        {
            try {
                Thread.sleep(50);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}
